/**
 *******************************************************************************************************************************************
 * @file        dev_dac.c
 * @brief       DAC 音频播放
 * @details     /
 * @since       Change Logs:
 * Date         Author       Notes
 * 2022-12-08   lzh          the first version
 * @remark		/
 *******************************************************************************************************************************************
 * @attention
 *
 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS WITH CODING INFORMATION
 * REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. AS A RESULT, SYNWIT SHALL NOT BE HELD LIABLE
 * FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
 * OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONN-
 * -ECTION WITH THEIR PRODUCTS.
 *
 * @copyright   2012 Synwit Technology
 *******************************************************************************************************************************************
 */
#include "dev_dac.h"
#include "version.h"

/*******************************************************************************************************************************************
 * Private Define
 *******************************************************************************************************************************************/
/** DAC 配置宏 */
#define DAC_TIMR                    TIMR0
#define DAC_DMA_HS                  DMA_EXHS_TIMR0

#if (SWM34S_LCM_PCBV == SWM34SCE_PIN48_A2)
/* 没有多余 IO 实现 MUTE STB */

    /** MUTE 脚初始化输出 */
    #define MUTE_STB_INIT()             //GPIO_Init(GPIOD, PIN11, 1, 0, 0, 0)
    /** MUTE 脚高电平静音控制 (eg : enable = 1 使能静音;            enable = 0 导通声音) */
    #define MUTE_STB_SET(enable)        //( GPIOD->DATAPIN11 = ( (enable) ? 1 : 0 ) )

#elif (SWM34S_LCM_PCBV == SWM34SRE_PIN64_A001)

    /** MUTE 脚初始化输出(与 SD_DET 共用, 当插入 SD 卡时会被拉高, 故此时 STB 控制无效<考虑转用 C8 - TP_MISO >) */
    #define MUTE_STB_INIT()         GPIO_Init(GPIOM, PIN3, 1, 0, 0, 0)
    /** MUTE 脚高电平静音控制 (eg : enable = 1 使能静音;            enable = 0 导通声音) */
    #define MUTE_STB_SET(enable)    ( GPIOM->DATAPIN3 = ( (enable) ? 1 : 0 ) )

#else /* SWM34SVET6_Pin100 */

    /** MUTE 脚初始化输出 */
    #define MUTE_STB_INIT()         GPIO_Init(GPIOD, PIN11, 1, 0, 0, 0)
    /** MUTE 脚高电平静音控制 (eg : enable = 1 使能静音;            enable = 0 导通声音) */
    #define MUTE_STB_SET(enable)    ( GPIOD->DATAPIN11 = ( (enable) ? 1 : 0 ) )

#endif
/*******************************************************************************************************************************************
 * Public Constant
 *******************************************************************************************************************************************/
/** 正弦波音频 - DAC 测试 */
const uint16_t Sin_Data[100] = {
    2048,  2176,  2304,  2431,  2557,  2680,  2801,  2919,  3034,  3144,
    3251,  3352,  3449,  3540,  3625,  3704,  3776,  3841,  3900,  3951,
    3994,  4030,  4058,  4078,  4090,  4095,  4090,  4078,  4058,  4030,
    3994,  3951,  3900,  3841,  3776,  3704,  3625,  3540,  3449,  3352,
    3251,  3144,  3034,  2919,  2801,  2680,  2557,  2431,  2304,  2176,
    2047,  1919,  1791,  1664,  1538,  1415,  1294,  1176,  1061,   951,
     844,   743,   646,   555,   470,   391,   319,   254,   195,   144,
     101,    65,    37,    17,     5,     1,     5,    17,    37,    65,
     101,   144,   195,   254,   319,   391,   470,   555,   646,   743,
     844,   951,  1061,  1176,  1294,  1415,  1538,  1664,  1791,  1919,
};

/*******************************************************************************************************************************************
 * Private Variable
 *******************************************************************************************************************************************/
/** 中断标志 */
typedef enum
{
    NO = 0, /**< 未触发中断 */
    OK      /**< 已触发中断 */
    /* 可以枚举拓展 ++ 累计触发次数 */
} irq_flag_t;

static volatile irq_flag_t IRQ_Flag_Audio = NO; /**< DAC_DMA 传输完成标志 */

/*******************************************************************************************************************************************
 * Public Function
 *******************************************************************************************************************************************/
/**
 * @brief   DMA ISR Callback (DAC 所用的通道中断触发处理)
 */
void isr_dma_dac(void)
{
    if (DMA_CH_INTStat(DAC_DMA_CHN, DMA_IT_DONE))
    {
        DMA_CH_INTClr(DAC_DMA_CHN, DMA_IT_DONE);

        IRQ_Flag_Audio = OK;
    }
}

/**
 * @brief   DAC DMA 判断是否传输完成
 * @param   /
 * @retval  0 : 传输完成    1 : 未完成/未开启传输
 */
uint8_t dac_dma_transfer_done(void)
{
    if (IRQ_Flag_Audio == OK)
    {
        IRQ_Flag_Audio = NO;
        return 0;
    }
    return 1;
}

/**
 * @brief   配置 DAC 驱动端口以及功放静音控制脚, 开启声音
 */
void dac_port_init(void)
{
#if (SWM34S_LCM_PCBV != SWM34SCE_PIN48_A2)
    /* MPU 屏 RGB 模式下 D2 用作 SPI 初始化片选信号 */
    PORT_Init(PORTD, PIN2, PORTD_PIN2_DAC_OUT, 0);
#endif
    
    MUTE_STB_INIT();
    MUTE_STB_SET(0);
}

/**
 * @brief   恢复 DAC 驱动端口以及功放静音控制脚的默认状态, 使能静音
 */
void dac_port_deinit(void)
{
#if (SWM34S_LCM_PCBV != SWM34SCE_PIN48_A2)
    /* MPU 屏 RGB 模式下 D2 用作 SPI 初始化片选信号 */
    GPIO_Init(GPIOD, PIN2, 0, 0, 1, 0);
    //GPIO_AtomicClrBit(GPIOD, PIN2);
#endif
    
    MUTE_STB_INIT();
    MUTE_STB_SET(1);
}

/**
 * @brief   初始化 DAC 模块
 */
void dac_init(void)
{
    dac_port_init();
    MUTE_STB_SET(1);

    DAC_Init(DAC, DAC_FORMAT_MSB12B); /* DHR 高 12 位 传输给 DOR */
    DAC_Open(DAC);
    
    DAC->DHR = (4095 >> 1) << 4; /* 高 12 bit 有效, 输出 1.65V 白噪声 */
    while (DAC->SR & DAC_SR_DHRFULL_Msk) __NOP();
}

/**
 * @brief   DAC_DMA 配置, 采用 TIMR 触发 DMA 步进传输
 * @param   addr : 数据源地址 (uint16_t *)
 * @param   count : 传输 Unit 个数 (/ 16bit)
 * @param   frequency : 音频采样率 (/ Hz)
 * @retval  /
 * @note    DMA 配置为外部 trigger 信号启动时, DMA 其他通道不工作, 此问题只能尽量避让绕开应用
 * 而 DMA 配置为 源侧/目标侧 外设 握手信号不会导致此问题.
 */
void dac_dma_init(uint16_t *addr, uint32_t count, uint32_t frequency)
{
    DMA_InitStructure DMA_initStruct;

    DMA_initStruct.Mode = DMA_MODE_SINGLE;
    DMA_initStruct.Unit = DMA_UNIT_HALFWORD;
    DMA_initStruct.Count = count;
    DMA_initStruct.SrcAddr = (uint32_t)addr;
    DMA_initStruct.SrcAddrInc = 1;
    DMA_initStruct.DstAddr = (uint32_t)&DAC->DHR;
    DMA_initStruct.DstAddrInc = 0;
    DMA_initStruct.Priority = DMA_PRI_LOW;
    DMA_initStruct.INTEn = DMA_IT_DONE;
    
    DMA_initStruct.Handshake = DAC_DMA_HS; /* 握手信号由外部 TIMR_x 触发 (注意: DMA 配置为外部 trigger 信号启动时, DMA 其他通道不工作, 此问题只能尽量避让绕开应用) */

    DMA_CH_Init(DAC_DMA_CHN, &DMA_initStruct);
    DMA_CH_Open(DAC_DMA_CHN);
    
    /* 控制按音频采样率播放音频, 每 ? 微秒 触发 DMA 向 DAC 搬运 1 个 Uint */
    TIMR_Init(DAC_TIMR, TIMR_MODE_TIMER, CyclesPerUs, 1000000 / frequency, 0);
    TIMR_Start(DAC_TIMR);

    MUTE_STB_SET(0);
}

/**
 * @brief   DAC_DMA 配置恢复初始默认状态
 */
void dac_dma_deinit(void)
{
    MUTE_STB_SET(1);

    TIMR_Stop(DAC_TIMR); /* 关闭触发源 */
    
    DMA_CH_Close(DAC_DMA_CHN);
    
    DAC->DHR = (4095 >> 1) << 4; /* 高 12 bit 有效, 输出 1.65V 白噪声 */
    while (DAC->SR & DAC_SR_DHRFULL_Msk) __NOP();
    
    /* 关闭后须重新初始化 DAC, 一般不关
    DAC_Close(DAC);*/
}
